﻿Imports System.Xml
Imports System.IO

Module mdlParse
    Private Blocks As Collection
    Private Ports As Collection
    Private Connectors As Collection

#Region "XMLParse"
    Public Function XMLParse(ByVal editor As shpEditor) As String
        Dim blk As shpBlock, writer As XmlWriter, swriter As StringWriter
        swriter = New StringWriter
        writer = XmlWriter.Create(swriter)
        writer.WriteStartDocument()
        writer.WriteStartElement("BPEditor")
        writer.WriteStartElement("Blocks")
        For Each blk In editor.GetBlocks
            writer.WriteStartElement("Block")
            writer.WriteAttributeString("Key", blk.Key)
            writer.WriteAttributeString("Label", blk.Label)
            writer.WriteAttributeString("Left", blk.nLeft)
            writer.WriteAttributeString("Top", blk.nTop)
            writer.WriteAttributeString("Width", blk.nWidth)
            writer.WriteAttributeString("Height", blk.nHeight)
            XmlWritePorts(blk, writer)
            writer.WriteEndElement()
        Next
        writer.WriteEndElement()
        XmlWritePorts(editor, writer)
        XmlWriteConnectors(editor, writer)
        writer.WriteEndElement()
        writer.WriteEndDocument()
        writer.Close()
        XMLParse = swriter.ToString
    End Function

    Private Function XmlWritePorts(ByVal blk As Object, ByVal writer As XmlWriter) As Boolean
        Dim shp As shpPort
        writer.WriteStartElement("Ports")
        For Each shp In blk.GetActivators
            writer.WriteStartElement("Activator")
            writer.WriteAttributeString("Key", shp.Key)
            writer.WriteAttributeString("Tooltip", shp.ToolTip.Content)
            XmlWriteLabel(shp, writer)
            writer.WriteEndElement()
        Next
        For Each shp In blk.GetEvents
            writer.WriteStartElement("Event")
            writer.WriteAttributeString("Key", shp.Key)
            writer.WriteAttributeString("Tooltip", shp.ToolTip.Content)
            XmlWriteLabel(shp, writer)
            writer.WriteEndElement()
        Next
        For Each shp In blk.GetInputs
            writer.WriteStartElement("Input")
            writer.WriteAttributeString("Key", shp.Key)
            writer.WriteAttributeString("Tooltip", shp.ToolTip.Content)
            XmlWriteLabel(shp, writer)
            writer.WriteEndElement()
        Next
        For Each shp In blk.GetOutputs
            writer.WriteStartElement("Output")
            writer.WriteAttributeString("Key", shp.Key)
            writer.WriteAttributeString("Tooltip", shp.ToolTip.Content)
            XmlWriteLabel(shp, writer)
            writer.WriteEndElement()
        Next
        writer.WriteEndElement()
        XmlWritePorts = True
    End Function

    Private Function XmlWriteLabel(ByVal prt As shpPort, ByVal writer As XmlWriter) As Boolean
        Dim lbl As clsLabel
        lbl = prt.Label
        writer.WriteStartElement("Label")
        writer.WriteAttributeString("Text", lbl.Text)
        writer.WriteAttributeString("Left", lbl.nLeft)
        writer.WriteAttributeString("Top", lbl.nTop)
        writer.WriteEndElement()
        XmlWriteLabel = True
    End Function

    Private Function XmlWriteConnectors(ByVal blk As Object, ByVal writer As XmlWriter) As Boolean
        Dim con As shpConnector, hol As clsHolder
        writer.WriteStartElement("Connectors")
        For Each con In blk.GetConnectors
            writer.WriteStartElement("Connector")
            writer.WriteAttributeString("Key", con.Key)
            If con.LeftPort IsNot Nothing Then
                writer.WriteAttributeString("Port1", con.LeftPort.Key)
            Else
                writer.WriteAttributeString("Port1", "")
            End If
            If con.LeftPort IsNot Nothing Then
                writer.WriteAttributeString("Port2", con.RightPort.Key)
            Else
                writer.WriteAttributeString("Port2", "")
            End If
            writer.WriteStartElement("Holders")
            hol = con.LeftHolder
            While hol IsNot Nothing
                writer.WriteStartElement("Holder")
                writer.WriteAttributeString("Key", hol.Key)
                writer.WriteAttributeString("Left", hol.nLeft)
                writer.WriteAttributeString("Top", hol.nTop)
                writer.WriteEndElement()
                hol = hol.RightHolder
            End While
            writer.WriteEndElement()
            writer.WriteEndElement()
        Next
        writer.WriteEndElement()
        XmlWriteConnectors = True
    End Function
#End Region

#Region "XMLPack"
    Public Function XMLPack(ByVal editor As shpEditor, ByVal content As String) As Boolean
        Dim reader As XmlReader = XmlReader.Create(New StringReader(content))
        Blocks = New Collection
        Ports = New Collection
        Connectors = New Collection
        While reader.Read()
            If reader.IsStartElement Then
                Select Case reader.Name
                    Case "Blocks"
                        XmlReadBlocks(editor, reader.ReadSubtree)
                    Case "Ports"
                        XmlReadPorts(editor, reader.ReadSubtree)
                    Case "Connectors"
                        XmlReadConnectors(editor, reader.ReadSubtree)
                End Select
            End If
        End While
        XMLPack = True
    End Function

    Private Function XmlReadBlocks(ByVal edi As shpEditor, ByVal reader As XmlReader) As Boolean
        Dim r As XmlReader, blk As shpBlock, lbl As String, left As Double, top As Double, key As String, wid As Double, hei As Double
        Dim zx As Double, zy As Double
        While reader.ReadToFollowing("Block")
            blk = Nothing : key = Nothing : lbl = 0 : left = 0 : top = 0 : wid = 0 : hei = 0
            zx = edi.ZoomX : zy = edi.ZoomY
            left = CDbl(reader.GetAttribute("Left")) * zx
            top = CDbl(reader.GetAttribute("Top")) * zy
            wid = CDbl(reader.GetAttribute("Width")) * zx
            hei = CDbl(reader.GetAttribute("Height")) * zy
            lbl = reader.GetAttribute("Label")
            key = reader.GetAttribute("Key")
            blk = edi.AddBlock(left, top)
            blk.Label = lbl
            blk.Shape.Width = wid
            blk.Shape.Height = hei
            If key IsNot Nothing Then
                Blocks.Add(blk, key)
            Else
                Blocks.Add(key)
            End If
            r = reader.ReadSubtree
            If r.ReadToFollowing("Ports") Then
                XmlReadPorts(blk, reader.ReadSubtree)
            End If
        End While
        XmlReadBlocks = True
    End Function

    Private Function XmlReadPorts(ByVal blk As Object, ByVal reader As XmlReader) As Boolean
        Dim r As XmlReader, prt As shpPort, key As String, ttp As String
        While reader.Read()
            If reader.IsStartElement Then
                prt = Nothing : key = Nothing : ttp = ""
                Select Case reader.Name
                    Case "Activator"
                        prt = blk.AddActivator()
                    Case "Event"
                        prt = blk.AddEvent()
                    Case "Input"
                        prt = blk.AddInput()
                    Case "Output"
                        prt = blk.AddOutput()
                End Select
                If prt IsNot Nothing Then
                    key = reader.GetAttribute("Key")
                    ttp = reader.GetAttribute("Tooltip")
                    prt.ToolTip.Content = ttp
                    r = reader.ReadSubtree
                    If r.ReadToFollowing("Label") Then
                        XmlReadLabel(prt, r)
                    End If
                    If key IsNot Nothing Then
                        Ports.Add(prt, key)
                    Else
                        Ports.Add(prt)
                    End If
                End If
            End If
        End While
        XmlReadPorts = True
    End Function

    Private Function XmlReadLabel(ByVal prt As shpPort, ByVal reader As XmlReader) As Boolean
        Dim lbl As clsLabel, edi As shpEditor, lef As Double, top As Double
        On Error GoTo Label_Exit
        lbl = Nothing : lef = 0 : top = 0
        edi = GetEditor(prt)
        lbl = prt.Label
        lbl.Text = reader.GetAttribute("Text")
        lef = reader.GetAttribute("Left")
        top = reader.GetAttribute("Top")
        lbl.MoveShape(lef * edi.ZoomX, top * edi.ZoomY)
        XmlReadLabel = True
Label_Exit:
    End Function

    Private Function XmlReadConnectors(ByVal edi As shpEditor, ByVal reader As XmlReader) As Boolean
        Dim r2 As XmlReader, r1 As XmlReader, lport As String, rport As String
        Dim pnt(0) As Point, cnt As Integer, con As shpConnector, key As String
        While reader.ReadToFollowing("Connector")
            lport = reader.GetAttribute("Port1")
            rport = reader.GetAttribute("Port2")
            key = reader.GetAttribute("Key")
            r1 = reader.ReadSubtree
            If r1.ReadToFollowing("Holders") Then
                r2 = reader.ReadSubtree
                cnt = 0
                While r2.Read()
                    If r2.IsStartElement Then
                        If reader.Name = "Holder" Then
                            ReDim Preserve pnt(cnt)
                            pnt(cnt).X = CDbl(r2.GetAttribute("Left")) * edi.ZoomX
                            pnt(cnt).Y = CDbl(r2.GetAttribute("Top")) * edi.ZoomY
                            cnt += 1
                        End If
                    End If
                End While
            End If
            If cnt > 0 Then
                con = edi.AddConnector(pnt)
                If Ports.Contains(lport) Then
                    con.SetPort(con.LeftHolder, Ports(lport))
                End If
                If Ports.Contains(rport) Then
                    con.SetPort(con.RightHolder, Ports(rport))
                End If
                Connectors.Add(con, key)
            End If
        End While
        XmlReadConnectors = True
    End Function
#End Region
End Module
